#include <iostream>
#include <fstream>
#include <string>
#include "PPMC/PPMC.h"
#include "PPMC/test/PPMCTest.h"
#include "PPMC/CompresorAritmeticoBase.h"
#include <stdlib.h>

#define NUMERO_GRUPO "XX"

using namespace std;

void showFileSize(const string &archivo)
{
	FILE * pFile;
	float size;

	pFile = fopen (archivo.c_str(),"rb");

	fseek (pFile, 0, SEEK_END);
	size=ftell (pFile);
	fclose (pFile);

	cout << "Tamano del archivo " << archivo << ": ";

	if (size<1024)
	{
		cout << size << " bytes" << endl;
		return;
	}

	size=size/1024;

	if (size<1024)
	{
		cout << size << " KB" << endl;
		return;
	}

	size=size/1024;

	if (size<1024)
	{
		cout << size << " MB" << endl;
		return;
	}

	size=size/1024;

	cout << size << " GB" << endl;
}

/**
 * opciones:
 * 	modo:
 * 		-c comprimir [default]
 * 		-x descomprimir
 *	orden:
 * 		-orden <valor> [default:6]
 * 		valores posibles: [0..inf]
 * 	tipo de modelo:
 * 		-modelo <valor> [default: ie]
 * 		valores posibles:
 * 			'n': Normal
 * 			'eh': Envejecimiento hiperbólico
 * 			'ee': Envejecimiento exponencial
 * 				opciones:
 * 					-termino-independiente <valor> [default: 2]
 * 						valores posibles: [0..inf]
 * 					-factor <valor> [default: 1.1426]
 * 						valores posibles: [0..inf]
 * 			'c': Cuadratico
 * 			'ie': Inicializa ESC en 1 e incremento 3
 * 	mostrar tamaño archivo:
 * 		-mostrar-tamano [defaul: no se muestra]
 * 	nombre del archivo (obligatorio):
 * 		Debe ser el último parámetro.
 */
int TP(int argc, char *argv[])
{
	std::map<string,string> parametros;
    char operacion='c';
    Contexto::Orden orden=6;
    string tipoModelo="ie";
    unsigned short terminoIndependiente=2;
    double factor=1.1426;
    bool mostrarTamano=false;

	for (int i=1; i<(argc-1); i++)
	{
		string parametro(argv[i]);

		if (parametro=="-c"||parametro=="-x")
			operacion=parametro.c_str()[1];
		else if (parametro=="-orden")
			orden=atoi(argv[i+1]);
		else if (parametro=="-modelo")
			tipoModelo=argv[i+1];
		else if (parametro=="-termino-independiente")
			terminoIndependiente=atoi(argv[i+1]);
		else if (parametro=="-factor")
			factor=atof(argv[i+1]);
		else if (parametro=="-mostrar-tamano")
			mostrarTamano=true;
	}

	string nombreArchivo=argv[argc-1];

    ifstream entrada;
    ofstream salida;
    Modelo *modelo;
    ICompresor *ca=NULL;

    if (tipoModelo=="n")
        modelo=new Modelo();
    else if (tipoModelo=="eh")
        modelo=new ModeloConEnvejecimientoHiperbolico();
    else if (tipoModelo=="ee")
        modelo=new ModeloConEnvejecimientoExponencial(
			terminoIndependiente,factor);
    else if (tipoModelo=="c")
        modelo=new ModeloCuadratico();
    else if (tipoModelo=="ie")
        modelo=new ModeloInicializaEsc();

    PPMC *ppmc=PPMC::getNewInstance(orden,ca,modelo);

    if (operacion=='c')
    {
    	if (mostrarTamano)
    		showFileSize(nombreArchivo);
        entrada.open(nombreArchivo.c_str(),ios_base::in);
        salida.open((nombreArchivo+"."+NUMERO_GRUPO).c_str(),ios_base::trunc | ios_base::binary);
        ppmc->comprimir(entrada,salida);
    }
    else
    {
        entrada.open(nombreArchivo.c_str(),ios_base::in | ios_base::binary);
        nombreArchivo.replace(nombreArchivo.length()-3,3,"");
        salida.open(nombreArchivo.c_str(),ios_base::trunc);
        ppmc->descomprimir(entrada,salida);
    }

    entrada.close();
    salida.close();

    PPMC::deleteInstance();

	if (mostrarTamano)
		showFileSize(nombreArchivo+"."+NUMERO_GRUPO);

	return 0;
}

int test(int argc, char *argv[])
{
	modeloTest();

	contextoTest();

	ppmcTest();

	return 0;
}

int maimnn(int argc, char *argv[])
{
	if ((argc>=2)&&((string(argv[1]))==string("test")))
		return test(argc,argv);
	else
		return TP(argc,argv);
}
